home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / UTILITY / XSPAWN.ARJ / XSPAWNVE.C < prev    next >
Text File  |  1991-05-04  |  16KB  |  582 lines

  1. /*
  2.  *                   XSPAWN
  3.  *                Version 1.33
  4.  *  (C) Copyright 1990 Whitney Software, Inc.
  5.  *             All Rights Reserved
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <errno.h>
  11. #include <string.h>
  12. #ifdef LATTICE
  13. #include <dos.h>
  14. #else
  15. #include <io.h>
  16. #endif
  17. #include "xspawnp.h"
  18.  
  19. typedef struct _vector
  20. {
  21.     char number;                       /* vector number */
  22.     char flag;                         /* 0-CURRENT, 1-IRET, 2-free, 3-end */
  23.     unsigned int vseg;                 /* vector segment */
  24.     unsigned int voff;                 /* vector offset */
  25. }
  26. VECTOR;
  27.  
  28. static void savevect( void );
  29. static int testfile( char *, char *, int * );
  30. static int tempfile( char *, int * );
  31. static int cmdenv( char **, char **, char *, char **, char ** );
  32. static int doxspawn( char *, char **, char ** );
  33. #ifdef LATTICE
  34. extern int __xspawn( char *, char *, char *, VECTOR *, int, int, char *, int );
  35. extern int __xsize( unsigned int, long *, long * );
  36. extern int __chkems( char *, int * );
  37. extern int __savemap( char * );
  38. extern int __restmap( char * );
  39. extern int __getems( int, int * );
  40. extern int __dskspace( int, unsigned int *, unsigned int * );
  41. extern int __getrc( void );
  42. extern int __create( char *, int * );
  43. extern int __getcd( int, char * );
  44. extern int __getdrv( void );
  45. extern void __getvect( int, unsigned int *, unsigned int * );
  46. extern void __setvect( VECTOR * );
  47. #else
  48. extern int _xspawn( char *, char *, char *, VECTOR *, int, int, char *, int );
  49. extern int _xsize( unsigned int, long *, long * );
  50. extern int _chkems( char *, int * );
  51. extern int _savemap( char * );
  52. extern int _restmap( char * );
  53. extern int _getems( int, int * );
  54. extern int _dskspace( int, unsigned int *, unsigned int * );
  55. extern int _getrc( void );
  56. extern int _create( char *, int * );
  57. extern int _getcd( int, char * );
  58. extern int _getdrv( void );
  59. extern void _getvect( int, unsigned int *, unsigned int * );
  60. extern void _setvect( VECTOR * );
  61. #endif
  62.  
  63. #ifdef LATTICE
  64. extern char **environ;
  65. #endif
  66.  
  67. int _swap = 0;                         /* if 0, do swap */
  68. char *_swappath = NULL;                /* swap path */
  69. int _useems = 0;                       /* if 0, use EMS */
  70. int _required = 0;                     /* child memory requirement in K */
  71. static long swapsize;                  /* swap size requirement in bytes */
  72. static int ems = 2;                    /* if 0, EMS is available */
  73. static int mapsize;                    /* size of page map information */
  74. static unsigned int tempno = 1;        /* tempfile number */
  75. static char errtab[] =                 /* error table */
  76. {
  77.     0,
  78.     EINVAL,
  79.     ENOENT,
  80.     ENOENT,
  81.     EMFILE,
  82.     EACCES,
  83.     EBADF,
  84.     ENOMEM,
  85.     ENOMEM,
  86.     ENOMEM,
  87.     E2BIG,
  88.     ENOEXEC,
  89.     EINVAL,
  90.     EINVAL,
  91.     -1,
  92.     EXDEV,
  93.     EACCES,
  94.     EXDEV,
  95.     ENOENT,
  96.     -1
  97. };
  98. static VECTOR vectab1[] =
  99. {
  100.     0,    1,     0,  0,
  101.     1,    1,     0,  0,
  102.     2,    1,     0,  0,
  103.     3,    1,     0,  0,
  104.     0x1B, 1,     0,  0,
  105.     0x23, 1,     0,  0,
  106.     0,    2,     0,  0,                /* free record */
  107.     0,    2,     0,  0,                /* free record */
  108.     0,    2,     0,  0,                /* free record */
  109.     0,    2,     0,  0,                /* free record */
  110.     0,    2,     0,  0,                /* free record */
  111.     0,    2,     0,  0,                /* free record */
  112.     0,    2,     0,  0,                /* free record */
  113.     0,    2,     0,  0,                /* free record */
  114.     0,    2,     0,  0,                /* free record */
  115.     0,    2,     0,  0,                /* free record */
  116.     0,    2,     0,  0,                /* free record */
  117.     0,    2,     0,  0,                /* free record */
  118.     0,    2,     0,  0,                /* free record */
  119.     0,    2,     0,  0,                /* free record */
  120.     0,    3,     0,  0                 /* end record */
  121. };
  122. static VECTOR vectab2[ sizeof vectab1 / sizeof vectab1[ 0 ]];
  123.  
  124. int addvect( number, opcode )
  125. int number;
  126. int opcode;
  127. {
  128.     register VECTOR *vect = vectab1;
  129.  
  130.     if ( number < 0 || number > 0xFF ||
  131.         ( opcode != IRET && opcode != CURRENT ))
  132.     {
  133.         errno = EINVAL;
  134.         return( -1 );
  135.     }
  136.  
  137.     /* see if number is already in table */
  138.     while ( vect->flag != 3 && ( vect->flag == 2 ||
  139.         vect->number != ( char )number ))
  140.     {
  141.         vect++;
  142.     }
  143.  
  144.     if ( vect->flag == 3 )
  145.     {
  146.         /* look for a free record */
  147.         vect = vectab1;
  148.         while ( vect->flag == CURRENT || vect->flag == IRET )
  149.             vect++;
  150.     }
  151.  
  152.     if ( vect->flag != 3 )
  153.     {
  154.         vect->number = ( char )number;
  155.         vect->flag = ( char )opcode;
  156.         if ( opcode == CURRENT )
  157. #ifdef LATTICE
  158.             __getvect( number, &vect->vseg, &vect->voff );
  159. #else
  160.             _getvect( number, &vect->vseg, &vect->voff );
  161. #endif
  162.         return( 0 );
  163.     }
  164.  
  165.     errno = ENOMEM;
  166.     return( -1 );
  167. }
  168.  
  169. static void savevect()
  170. {
  171.     register VECTOR *vect1 = vectab1;
  172.     register VECTOR *vect2 = vectab2;
  173.  
  174.     while ( vect1->flag != 3 )
  175.     {
  176.         if ( vect1->flag != 2 )
  177.         {
  178.             vect2->number = vect1->number;
  179.             vect2->flag = CURRENT;
  180. #ifdef LATTICE
  181.             __getvect( vect1->number, &vect2->vseg, &vect2->voff );
  182. #else
  183.             _getvect( vect1->number, &vect2->vseg, &vect2->voff );
  184. #endif
  185.         }
  186.         else
  187.             vect2->flag = 2;           /* free */
  188.         vect1++;
  189.         vect2++;
  190.     }
  191.     vect2->flag = 3;                   /* end */
  192. }
  193.  
  194. static int testfile( p, file, handle )
  195. register char *p;
  196. register char *file;
  197. int *handle;
  198. {
  199.     unsigned int startno = tempno;
  200.     int drive = ( *file | 32 ) - 96;   /* a = 1, b = 2, etc. */
  201.     int root;
  202.     unsigned int bytes;                /* bytes per cluster */
  203.     unsigned int clusters;             /* free clusters */
  204.     int need;                          /* clusters needed for swap file */
  205.     int rc;                            /* return code */
  206.  
  207.     if ( file + 2 == p )
  208.     {
  209.         *p++ = '\\';
  210. #ifdef LATTICE
  211.         if ( __getcd( drive, p ))      /* get current directory */
  212. #else
  213.         if ( _getcd( drive, p ))       /* get current directory */
  214. #endif
  215.             return( 1 );               /* invalid drive */
  216.         p = file + strlen( file );
  217.     }
  218.     else
  219.     {
  220.         *p = '\0';
  221.         if ( access( file, 0 ))
  222.             return( 1 );               /* path does not exist */
  223.     }
  224.     if ( *( p - 1 ) != '\\' && *( p - 1 ) != '/' )
  225.         *p++ = '\\';
  226.     if ( p - file == 3 )
  227.         root = 1;                      /* is root directory */
  228.     else
  229.         root = 0;                      /* is not root directory */
  230.     strcpy( p, "swp" );
  231.     p += 3;
  232.  
  233. #ifdef LATTICE
  234.     if ( __dskspace( drive, &bytes, &clusters ) != 0 )
  235. #else
  236.     if ( _dskspace( drive, &bytes, &clusters ) != 0 )
  237. #endif
  238.         return( 1 );                   /* invalid drive */
  239.     need = ( int )( swapsize / bytes );
  240.     if ( swapsize % bytes )
  241.         need++;
  242.     if ( root == 0 )                   /* if subdirectory */
  243.         need++;                        /* in case the directory needs space */
  244.     if ( clusters < ( unsigned int )need )
  245.         return( 1 );                   /* insufficient free disk space */
  246.  
  247.     do
  248.     {
  249. again:  tempno = ( ++tempno ) ? tempno : 1;
  250.         if ( tempno == startno )
  251.             return( 1 );               /* extremely unlikely */
  252. #ifdef LATTICE
  253.         stcu_d( p, tempno );
  254. #else
  255.         ltoa(( long )tempno, p, 10 );
  256. #endif
  257.     }
  258.     while ( !access( file, 0 ));
  259.  
  260. /*
  261.  *  The return code from _create will equal 80 if the user is running DOS 3.0
  262.  *  or above and the file was created by another program between the access
  263.  *  call and the _create call.
  264.  */
  265.  
  266. #ifdef LATTICE
  267.     if (( rc = __create( file, handle )) == 80 )
  268. #else
  269.     if (( rc = _create( file, handle )) == 80 )
  270. #endif
  271.         goto again;
  272.     return( rc );
  273. }
  274.  
  275. static int tempfile( file, handle )
  276. char *file;
  277. int *handle;
  278. {
  279.     register char *s = _swappath;
  280.     register char *p = file;
  281.  
  282.     if ( s )
  283.     {
  284.         for ( ;; s++ )
  285.         {
  286.             while ( *s && *s != ';' )
  287.                 *p++ = *s++;
  288.             if ( p > file )
  289.             {
  290.                 if ( p == file + 1 || file[ 1 ] != ':' )
  291.                 {
  292. #ifdef MSC4
  293.                     memcpy( file + 2, file, ( int )( p - file ));
  294. #else
  295.                     memmove( file + 2, file, ( int )( p - file ));
  296. #endif
  297. #ifdef LATTICE
  298.                     *file = ( char )( __getdrv() + 'a' );
  299. #else
  300.                     *file = ( char )( _getdrv() + 'a' );
  301. #endif
  302.                     file[ 1 ] = ':';
  303.                     p += 2;
  304.                 }
  305.                 if ( testfile( p, file, handle ) == 0 )
  306.                     return( 0 );
  307.                 p = file;
  308.             }
  309.             if ( *s == '\0' )
  310.                 break;
  311.         }
  312.     }
  313.     else                               /* try the current directory */
  314.     {
  315. #ifdef LATTICE
  316.         *p++ = ( char )( __getdrv() + 'a' );
  317. #else
  318.         *p++ = ( char )( _getdrv() + 'a' );
  319. #endif
  320.         *p++ = ':';
  321.         if ( testfile( p, file, handle ) == 0 )
  322.             return( 0 );
  323.     }
  324.  
  325.     errno = EACCES;
  326.     return( 1 );
  327. }
  328.  
  329. static int cmdenv( argv, envp, command, env, memory )
  330. char **argv;
  331. char **envp;
  332. char *command;
  333. char **env;
  334. char **memory;
  335. {
  336.     register char **vp;
  337.     unsigned int elen = 0;             /* environment length */
  338.     char *p;
  339.     int cnt;
  340.     int len;
  341.  
  342.     /* construct environment */
  343.  
  344.     if ( envp == NULL )
  345.         envp = environ;
  346.  
  347.     if ( envp )
  348.     {
  349.         for ( vp = envp; *vp; vp++ )
  350.         {
  351.             elen += strlen( *vp ) + 1;
  352.             if ( elen > 32766 )        /* 32K - 2 */
  353.             {
  354.                 errno = E2BIG;
  355.                 return( -1 );
  356.             }
  357.         }
  358.     }
  359.  
  360.     if (( p = malloc( ++elen + 15 )) == NULL )
  361.     {
  362.         errno = ENOMEM;
  363.         return( -1 );
  364.     }
  365.     *memory = p;
  366.  
  367.     *( unsigned int * )&p = *( unsigned int * )&p + 15 & ~15;
  368.     *env = p;
  369.  
  370.     if ( envp )
  371.     {
  372.         for ( vp = envp; *vp; vp++ )
  373.             p = strchr( strcpy( p, *vp ), '\0' ) + 1;
  374.     }
  375.  
  376.     *p = '\0';                         /* final element */
  377.  
  378.     /* construct command-line */
  379.  
  380.     vp = argv;
  381.     p = command + 1;
  382.     cnt = 0;
  383.  
  384.     if ( *vp )
  385.     {
  386.         while ( *++vp )
  387.         {
  388.             *p++ = ' ';
  389.             cnt++;
  390.             len = strlen( *vp );
  391.             if ( cnt + len > 125 )
  392.             {
  393.                 errno = E2BIG;
  394.                 free( *memory );
  395.                 return( -1 );
  396.             }
  397.             strcpy( p, *vp );
  398.             p += len;
  399.             cnt += len;
  400.         }
  401.     }
  402.  
  403.     *p = '\r';
  404.     *command = ( char )cnt;
  405.  
  406.     return(( int )elen );              /* return environment length */
  407. }
  408.  
  409. static int doxspawn( path, argv, envp )
  410. char *path;                      /* file to be executed */
  411. char *argv[];                    /* array of pointers to arguments */
  412. char *envp[];                    /* array of pointers to environment strings */
  413. {
  414.     register int rc = 0;               /* assume do xspawn */
  415.     int doswap = 0;                    /* assume do swap */
  416.     int elen;                          /* environment length */
  417.     char *memory;
  418.     char *env;                         /* environment */
  419.     char command[ 128 ];               /* command-line */
  420.     long totalsize;                    /* parent and free memory in bytes */
  421.     int handle;
  422.     int pages;
  423.     char file[ 79 ];
  424.     char *mapbuf = NULL;               /* buffer for map information */
  425.  
  426.     /* construct the command-line and the environment */
  427.     if (( elen = cmdenv( argv, envp, command, &env, &memory )) == -1 )
  428.         return( -1 );
  429.  
  430.     if ( _swap == 0 )
  431.     {
  432.         if ( _useems == 0 )
  433.         {
  434.             if ( ems == 2 )
  435. #ifdef LATTICE
  436.                 ems = __chkems( "EMMXXXX0", &mapsize );
  437. #else
  438.                 ems = _chkems( "EMMXXXX0", &mapsize );
  439. #endif
  440.             if ( ems == 0 && ( mapbuf = malloc( mapsize )) == NULL )
  441.             {
  442.                 errno = ENOMEM;
  443.                 free( memory );
  444.                 return( -1 );
  445.             }
  446.         }
  447. #ifdef LATTICE
  448.         if (( rc = __xsize(( unsigned int )(( unsigned long )_PSP >> 16 ),
  449.             &swapsize, &totalsize )) == 0 )
  450. #else
  451.         if (( rc = _xsize( _psp, &swapsize, &totalsize )) == 0 )
  452. #endif
  453.         {
  454.             if ( _required == 0 ||
  455.                 totalsize - swapsize - 272 < (( long )_required << 10 ))
  456.             {
  457.                 if ( ems == 0 && _useems == 0 )
  458.                 {
  459.                     pages = ( int )( swapsize >> 14 );
  460.                     if ((( long )pages << 14 ) < swapsize )
  461.                         pages++;
  462. #ifdef LATTICE
  463.                     if ( __savemap( mapbuf ) == 0 &&
  464.                         __getems( pages, &handle ) == 0 )
  465. #else
  466.                     if ( _savemap( mapbuf ) == 0 &&
  467.                         _getems( pages, &handle ) == 0 )
  468. #endif
  469.                         *file = '\0';  /* use EMS */
  470.                     else if ( tempfile( file, &handle ) != 0 )
  471.                         rc = -1;       /* don't do xspawn */
  472.                 }
  473.                 else if ( tempfile( file, &handle ) != 0 )
  474.                     rc = -1;           /* don't do xspawn */
  475.             }
  476.             else
  477.                 doswap = 1;            /* don't do swap */
  478.         }
  479.         else
  480.         {
  481.             errno = errtab[ rc ];
  482.             rc = -1;                   /* don't do xspawn */
  483.         }
  484.     }
  485.     else
  486.         doswap = 1;                    /* don't do swap */
  487.  
  488.     if ( rc == 0 )
  489.     {
  490.         savevect();                    /* save current vectors */
  491. #ifdef LATTICE
  492.         rc = __xspawn( path, command, env, vectab1, doswap, elen, file,
  493.             handle );
  494. #else
  495.         rc = _xspawn( path, command, env, vectab1, doswap, elen, file,
  496.             handle );
  497. #endif
  498. #ifdef LATTICE
  499.         __setvect( vectab2 );          /* restore saved vectors */
  500. #else
  501.         _setvect( vectab2 );           /* restore saved vectors */
  502. #endif
  503.         if ( rc == 0 )
  504. #ifdef LATTICE
  505.             rc = __getrc();            /* get child return code */
  506. #else
  507.             rc = _getrc();             /* get child return code */
  508. #endif
  509.         else
  510.         {
  511.             errno = errtab[ rc ];
  512.             rc = -1;
  513.         }
  514.         /*
  515.          *  If EMS was used, restore the page-mapping state of the expanded
  516.          *  memory hardware.
  517.          */
  518. #ifdef LATTICE
  519.         if ( doswap == 0 && *file == '\0' && __restmap( mapbuf ) != 0 )
  520. #else
  521.         if ( doswap == 0 && *file == '\0' && _restmap( mapbuf ) != 0 )
  522. #endif
  523.         {
  524.             errno = EACCES;
  525.             rc = -1;
  526.         }
  527.     }
  528.  
  529.     if ( mapbuf )
  530.         free( mapbuf );
  531.     free( memory );
  532.     return( rc );
  533. }
  534.  
  535. int xspawnve( modeflag, path, argv, envp )
  536. int modeflag;                    /* execution mode for parent process */
  537. register char *path;             /* file to be executed */
  538. char *argv[];                    /* array of pointers to arguments */
  539. char *envp[];                    /* array of pointers to environment strings */
  540. {
  541.     register char *p;
  542.     char *s;
  543.     int rc = -1;
  544.     char buf[ 80 ];
  545.  
  546.     if ( modeflag != P_WAIT )
  547.     {
  548.         errno = EINVAL;
  549.         return( -1 );
  550.     }
  551.  
  552.     p = strrchr( path, '\\' );
  553.     s = strrchr( path, '/' );
  554.     if ( p == NULL && s == NULL )
  555.         p = path;
  556.     else if ( p == NULL || s > p )
  557.         p = s;
  558.  
  559.     if ( strchr( p, '.' ))
  560.     {
  561.         if ( !access( path, 0 ))
  562.             rc = doxspawn( path, argv, envp );
  563.         /* If file not found, access will have set errno to ENOENT. */
  564.     }
  565.     else
  566.     {
  567.         strcpy( buf, path );
  568.         strcat( buf, ".com" );
  569.         if ( !access( buf, 0 ))
  570.             rc = doxspawn( buf, argv, envp );
  571.         else
  572.         {
  573.             strcpy( strrchr( buf, '.' ), ".exe" );
  574.             if ( !access( buf, 0 ))
  575.                 rc = doxspawn( buf, argv, envp );
  576.             /* If file not found, access will have set errno to ENOENT. */
  577.         }
  578.     }
  579.  
  580.     return( rc );
  581. }
  582.